/********************************************************************************
* @file    os_api.h
* @author  jianqiang.xue
* @version V1.0.0
* @date    2023-08-14
* @brief   NOS支持 事件、事件组、消息队列、互斥锁、软定时器
********************************************************************************/
#ifndef OS_API_H_
#define OS_API_H_
#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

#include "cx32l003_hal.h"
#include "s_task.h"

/// Timeout value.
#define OS_WAIT_FOREVER     0xFFFFFFFFU    ///< wait forever timeout value

/************************************OS_KERNEL************************************/
typedef enum {
    OS_OK                     =     0,       ///< function completed; no error or event occurred.
    OS_EVENT_SIGNAL           =  0x08,       ///< function completed; signal event occurred.
    OS_EVENT_MESSAGE          =  0x10,       ///< function completed; message event occurred.
    OS_EVENT_MAIL             =  0x20,       ///< function completed; mail event occurred.
    OS_EVENT_TIMEOUT          =  0x40,       ///< function completed; timeout occurred.
    OS_ERROR_PARAMETER        =  0x80,       ///< parameter error: a mandatory parameter was missing or specified an incorrect object.
    OS_ERROR_RESOURCE         =  0x81,       ///< resource not available: a specified resource was not available.
    OS_ERROR_TIMEOUTRESOURCE  =  0xC1,       ///< resource not available within given time: a specified resource was not available within the timeout period.
    OS_ERROR_ISR              =  0x82,       ///< not allowed in ISR context: the function cannot be called from interrupt service routines.
    OS_ERROR_ISRRECURSIVE     =  0x83,       ///< function called multiple times from ISR with same object.
    OS_ERROR_PRIORITY         =  0x84,       ///< system cannot determine priority or thread has illegal priority.
    OS_ERROR_NOMEMORY         =  0x85,       ///< system is out of memory: it was impossible to allocate or reserve memory for the operation.
    OS_ERROR_VALUE            =  0x86,       ///< value of a parameter is out of range.
    OS_ERROR_OS               =  0xFF,       ///< unspecified RTOS error: run-time error but no other error message fits.
} os_status;


#define os_kernel_initialize() s_task_init_system()

// 协程没有系统启动和停止
#define os_kernel_start() task_main(__await__, NULL)

static inline uint32_t os_kernel_stop(void) {
    return OS_OK;
}

#define os_delay(ms) s_task_msleep(__await__, ms)

static inline uint32_t os_get_tick(void) {
    return HAL_GetTick();
}

static inline uint32_t os_get_state(void) {
    return OS_OK;
}

static inline void* os_malloc(uint32_t size) {
    return NULL;
}

static inline void* os_calloc(uint32_t size) {
    return NULL;
}

static inline uint8_t os_free(void *p) {
    return NULL;
}

/************************************OS_THREAD************************************/
// 定义线程所需的变量和回调声明（请在全局区调用）
#define OS_THREAD_DECLARE(name, stacksz)                     \
    static int g_task_##name##_stack[stacksz / sizeof(int)]; \
    static void task_##name(__async__, void* arg);

// 创建线程(请在函数中使用)
#define OS_THREAD_CREATE(name) {                    \
    s_task_create(g_task_##name##_stack, sizeof(g_task_##name##_stack), task_##name, NULL); \
}

// 线程函数头
#define OS_THREAD_FUNC(name) static void task_##name(__async__, void* arg)

#define OS_THREAD_WAIT(name) s_task_join(__await__, g_task_##name##_stack);
/************************************OS_TIMER************************************/
// typedef enum {
//     OS_TIMER_ONCE     = 0,    ///< one-shot timer
//     OS_TIMER_PERIODIC = 1     ///< repeating timer
// } os_timer_t;

// #define OS_TIMER_STRUCT(name) g_##name##_timer_struct

// // 定义软定时器所需的变量和回调声明（请在全局区调用）
// #define OS_TIMER_DECLARE_N(name)                 \
//     Clock_Struct g_##name##_timer_struct; \
//     static void timer_##name##_cb(UArg arg);

// // 创建软定时器并指定周期类型(单次/循环)(请在函数中使用)
// #define OS_TIMER_CREATE(name, cycle_t, cycle_ms, arg) {      \
//     if (cycle_t == OS_TIMER_ONCE) {                                      \
//         Util_constructClock(&g_##name##_timer_struct, timer_##name##_cb, \
//                             cycle_ms, 0, false, (UArg)arg);              \
//     } else {                                                             \
//         Util_constructClock(&g_##name##_timer_struct, timer_##name##_cb, \
//                             cycle_ms, cycle_ms, false, (UArg)arg);       \
//     }                                                                    \
// }

// // 软定时器是运行状态吗
// #define OS_TIMER_IS_RUNNING()  Util_isActive(&g_##name##_timer_struct)

// // 启动软定时器(请在函数中使用)
// #define OS_TIMER_START(name) {                 \
//     Util_startClock(&g_##name##_timer_struct); \
// }

// // 启动软定时器(请在函数中使用)
// #define OS_TIMER_RESTART(name, ms) {                 \
//     Util_restartClock(&g_##name##_timer_struct, ms); \
// }

// // 停止软定时器(请在函数中使用)
// #define OS_TIMER_STOP(name) {                 \
//     Util_stopClock(&g_##name##_timer_struct); \
// }

/************************************OS_QUEUE************************************/
// 定义消息队列所需的变量和回调声明（请在全局区调用）
#define OS_MSG_DECLARE(name, num, struct) s_chan_declare(g_##name##_queue, struct, num)

// 创建消息队列(请在函数中使用)
#define OS_MSG_CREATE(name, num, struct) s_chan_init(g_##name##_queue, struct, num)

// 消息入队
#define OS_MSG_ENQUEUE_MSG(name, pmsg) s_chan_put(__await__, g_##name##_queue, (void *)pmsg)

// 消息出队
#define OS_MSG_DEQUEUE_MSG(name, pmsg) s_chan_get(__await__, g_##name##_queue, (void *)pmsg)

// 消息队列(数量)是空吗
#define OS_MSG_IS_EMPTY(name) (!s_chan_get_count(__await__, g_##name##_queue))

// 消息队列(数量)非空 
#define OS_MSG_NO_NULL(name) (s_chan_get_count(__await__, g_##name##_queue))
/************************************OS_SIGNAL************************************/

// 定义事件所需的变量和回调声明（请在全局区调用）
#define OS_SIGNAL_DECLARE(name) uint32_t g_signal_##name

// 创建事件组(请在函数中使用)
#define OS_SIGNAL_CREATE(name) g_signal_##name = 0

// 发送事件
#define OS_SIGNAL_POST(name, signal) g_signal_##name |= signal

// 发送事件(中断中使用)
#define OS_SIGNAL_POST_ISR(name, signal) {S_IRQ_DISABLE(); g_signal_##name |= signal; S_IRQ_ENABLE();}

// 等待事件
inline uint8_t os_signal_wait(uint32_t source_signal, uint32_t target_signal, uint32_t ms) {
    uint32_t cnt = 0;
    do {
        if (target_signal == 0 && source_signal != 0) return 0;
        if (target_signal != 0 && (target_signal & source_signal) != 0) return 0;
        //os_delay(1);
        cnt++;
    } while(cnt < ms);
    return 1;
}
#define OS_SIGNAL_PEND(name, target, ms) os_signal_wait(g_signal_##name, target, ms)

/************************************OS_EVENT************************************/

// 定义事件所需的变量和回调声明（请在全局区调用）
#define OS_EVENT_DECLARE(name) s_event_t g_event_##name

// 创建事件(请在函数中使用) 构造一个用作资源锁的信号量对象，
#define OS_EVENT_CREATE(name) s_event_init(&g_event_##name)

// 发送事件
#define OS_EVENTL_POST(name) s_event_set(&g_event_##name)

// 发送事件(中断中使用)
#define OS_EVENT_POST_ISR(name) {S_IRQ_DISABLE(); s_event_set(&g_event_##name); S_IRQ_ENABLE();}

// 等待事件
#define OS_EVENT_PEND(name, ms) s_event_wait_msec(&g_event_##name, ms)

#ifdef __cplusplus
}
#endif

#endif
